﻿#include "EditorSceneOutlineAbilityView.h"

#include "Widgets/RectangleWidget.h"
#include "Widgets/TextWidget.h"
#include "Framework/Editor.h"
#include "Theme/EditorTheme.h"
#include "Widgets/Mouse/MouseWidget.h"

#include "Output/Console.h"

#include "Widgets/Positioners/HorizontalPositionerWidget.h"
#include "Widgets/EditorImageButton.h"

#include "Asset/EditorDefaultPackage.h"
#include "Widgets/ImageWidget.h"

#include "Widgets/EditableText/EditorEditableTextView.h"
#include "Widgets/EditableText/EditorEditableTextViewModel.h"

void REditorSceneOutlineAbilityView::BindViewModel(TSharedObjectPtr<REditorAbilityViewModel> InViewModel)
{
    Super::BindViewModel(InViewModel);
    ViewModel=InViewModel;

    ViewModel->OnNodeTreeChanged.Bind([this]()
    {
        if(List)
        {
            UpdateList();
        }
    });

    NameEditView=NewObject<REditorEditableTextView>(this);
    NameEditView->BindViewModel(ViewModel->GetNameEditViewModel());
}

void REditorSceneOutlineAbilityView::CreateWidget(TSharedObjectPtr<RWidget> InParent)
{
    RootWidget=NewWidget<RWidget>(InParent);
    RootWidget->Anchor.Fill(InParent);

    auto EmptyText=NewWidget<RTextWidget>(RootWidget);
    EmptyText->Text=U"需要打开一个场景资产";
    EmptyText->Anchor.Fill(RootWidget);
    EmptyText->VerticalAlignment=ETextVerticalAlignment::Center;
    EmptyText->HorizontalAlignment=ETextHorizontalAlignment::Center;
    EmptyText->Visible=[this](){
        return !ViewModel->HasNodes();
    };

    auto HovorHighlight=NewWidget<RRectangleWidget>(RootWidget);
    HovorHighlight->FillColor= REditor::Get()->CurrentTheme->ItemHoverColor;
    HovorHighlight->Visible=[this](){
        return ViewModel->HaveHoveredNode();
    };
    HovorHighlight->Anchor.HorizontalFill(RootWidget);

    //for shortcut 
    //and also use IsFocused to check if the ability is focused
    Keyborad=NewWidget<RKeyboardWidget>(RootWidget);
    Keyborad->Anchor.Fill(RootWidget);
    Keyborad->OnKeyboardInput.Bind([this](const SKeyboardEvent& InEvent)
    {
        if(InEvent.KeyState!=EKeyState::Pressed)
        {
            return false;
        }

        switch(InEvent.Key)
        {
            case EKey::Delete:
            {
                ViewModel->DeleteFocusedNode();
                return true;
            }
            case EKey::F2:
            {
                ViewModel->RenameFocusedNode();
                return true;
            }
        }
        return false;
    });


    auto TotalMouse=NewWidget<RMouseWidget>(RootWidget);
    TotalMouse->Anchor.Fill(RootWidget);
    TotalMouse->OnClicked.BindLambda([this](const SMouseButtonEvent&){
        Keyborad->Focus();
        return true;
    });

    auto SelectHighlight=NewWidget<RRectangleWidget>(RootWidget);
    SelectHighlight->FillColor= [this]()-> SColor
    {
        if(Keyborad->IsFocused())
        {
            return REditor::Get()->CurrentTheme->ItemFocusSelectedColor;
        }
        else
        {
            return REditor::Get()->CurrentTheme->ItemSelectColor;
        }
    };
    SelectHighlight->Visible=[this]()->bool
    {
        return ViewModel->HaveSelectedNode();
    };
    SelectHighlight->Anchor.HorizontalFill(RootWidget);
        


    List=NewWidget<RWidget>(RootWidget);
    List->Anchor.Fill(RootWidget);
    List->Visible=[this](){
        return ViewModel->HasNodes();
    };
    RWidgetWeakPtr WeakList=List;
    UpdateList();



    HovorHighlight->Anchor.TopReference=[this,WeakList]()->RWidgetPtr
    {
        int64_t Index=ViewModel->GetHoveredNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakList->GetSubWidget(Index);
    };
    HovorHighlight->Anchor.BottomReference=[this,WeakList]()->RWidgetPtr
    {
        int64_t Index=ViewModel->GetHoveredNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakList->GetSubWidget(Index);
    };

    SelectHighlight->Anchor.TopReference=[this,WeakList]()->RWidgetPtr
    {
        int64_t Index=ViewModel->GetSelectedNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakList->GetSubWidget(Index);
    };

    SelectHighlight->Anchor.BottomReference=[this,WeakList]()->RWidgetPtr
    {
        int64_t Index=ViewModel->GetSelectedNodeIndex();
        if(Index==-1)
        {
            return nullptr;
        }
        return WeakList->GetSubWidget(Index);
    };


    //widget to edit the node name
    auto EditingNameBackground=NewWidget<RRectangleWidget>(InParent);
    EditingNameBackground->FillColor= 
        REditor::Get()->CurrentTheme->BackgroundColor;
    EditingNameBackground->BorderSize=1;
    EditingNameBackground->BorderColor=[this]()
    {
        if(!ViewModel->HasEditingNameError())
        {
            return REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColor;
        }
        else
        {
            return REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColorError;
        }
    };
    EditingNameBackground->Visible=[this](){return ViewModel->GetEditingNodeIndex()!=-1;};
    EditingNameBackground->Height=ViewModel->LineHeight;
    EditingNameBackground->Anchor.LeftReference=InParent;
    EditingNameBackground->Anchor.LeftOffset=[this]()->float
        {
            int64_t Index=ViewModel->GetEditingNodeIndex();
            if(Index==-1)
            {
                //is not visible
                return 0;
            }
            float Offset=ViewModel->GetNodeDepth(Index);
            return Offset;
        };
    EditingNameBackground->Anchor.RightReference=InParent;
    EditingNameBackground->Y=[this]()->float
    {
        int64_t Index=ViewModel->GetEditingNodeIndex();
        if(Index==-1)
        {
            return 0;
        }
        return ViewModel->LineHeight*Index;
    };

    auto NameEditError=NewWidget<RRectangleWidget>(EditingNameBackground);
    NameEditError->FillColor=REditor::Get()->CurrentTheme->ItemSelectColorError;
    NameEditError->BorderSize=1;
    NameEditError->BorderColor=REditor::Get()->CurrentTheme->ItemFocusSelectedBorderColorError;
    NameEditError->Visible=[this](){return ViewModel->HasEditingNameError();};
    NameEditError->Anchor.HorizontalFill(EditingNameBackground);
    NameEditError->Height=ViewModel->LineHeight;
    NameEditError->Anchor.TopReference=EditingNameBackground;
    NameEditError->Anchor.TopReferenceEdge=EVerticalWidgetEdge::Bottom;
    NameEditError->bClipSubWidgets=true;

    auto NameEditErrorText=NewWidget<RTextWidget>(NameEditError);
    NameEditErrorText->Anchor.VerticalCenterReference=NameEditError;
    NameEditErrorText->Anchor.LeftReference=NameEditError;
    NameEditErrorText->Anchor.LeftOffset=5;
    NameEditErrorText->Text=[this](){return ViewModel->GetEditingNameError();};

    NameEditView->CreateWidget(EditingNameBackground);

}

void REditorSceneOutlineAbilityView::FillOperations(TSharedObjectPtr<RWidget> InTitleBar)
{
    auto ButtonBar=NewWidget<RHorizontalPositionerWidget>(InTitleBar);
    ButtonBar->Anchor.VerticalCenterReference=InTitleBar;
    ButtonBar->Anchor.RightReference=InTitleBar;
    ButtonBar->Spacing=ViewModel->OperationInterval;
    ButtonBar->Height=ViewModel->OperationButtonSize;

    ButtonBar->Width= ViewModel->OperationButtonSize;

    auto AddNodeIcon = REditorDefaultPackage::Get()->GetIcon(U"AddNode_Highlight");

    auto AddNodeButton=WHE::CreateImageButton(
        AddNodeIcon
        ,CString(U"添加节点")
        ,[this](){
            ViewModel->AddNewNode();
        }
        ,ButtonBar
        ,ViewModel->OperationButtonSize
        ,ViewModel->OperationButtonImageSize
    );
    AddNodeButton->Anchor.VerticalFill(ButtonBar);
    AddNodeButton->Width=ViewModel->OperationButtonSize;

}

void REditorSceneOutlineAbilityView::UpdateList()
{
    List->ClearSubWidgets();

    for(int64_t NodeIndex=0;NodeIndex<ViewModel->GetVisibleNodeNum();NodeIndex++)
    {
        auto NodeWidget=NewWidget<RWidget>(List);
        NodeWidget->Height= ViewModel->LineHeight;
        NodeWidget->Y=ViewModel->LineHeight * NodeIndex;
        NodeWidget->Anchor.RightReference=List;
        NodeWidget->X=[this,NodeIndex]()
        {
            return ViewModel->GetNodeDepth(NodeIndex);
        };

        auto NodeIcon=NewWidget<RImageWidget>(NodeWidget);
        NodeIcon->Image=[this,NodeIndex]()
        {
            return ViewModel->GetNodeIcon(NodeIndex);
        };
        NodeIcon->Width=ViewModel->LineHeight;
        NodeIcon->Height=ViewModel->LineHeight;

        auto NodeText=NewWidget<RTextWidget>(NodeWidget);
        NodeText->Text=[this,NodeIndex](){
            return ViewModel->GetNodeText(NodeIndex);
        };
        NodeText->FontSize=ViewModel->FontSize;
        NodeText->VerticalAlignment=ETextVerticalAlignment::Center;
        NodeText->Anchor.VerticalFill(NodeWidget);
        NodeText->Anchor.LeftReference=NodeIcon;
        NodeText->Anchor.LeftReferenceEdge=EHorizontalWidgetEdge::Right;
        NodeText->Anchor.LeftOffset=5;
        NodeText->Anchor.RightReference=NodeWidget;

        auto Mouse=NewWidget<RMouseWidget>(NodeWidget);
        Mouse->Anchor.VerticalFill(NodeWidget);
        Mouse->Anchor.HorizontalFill(List);
        Mouse->OnEntered.BindLambda([this,NodeIndex](){
            ViewModel->SetHoveredNodeIndex(NodeIndex);
        });
        Mouse->OnExited.BindLambda([this](){
            ViewModel->SetHoveredNodeIndex(-1);
        });
        Mouse->OnClicked.BindLambda([this,NodeIndex](const SMouseButtonEvent& MouseEvent){
            ViewModel->OnLineClicked(NodeIndex);
            this->Keyborad->Focus();
            return true;
        });
    }

 
}
